﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;

namespace Hack.Net.Downloaders
{
    public class NetPercentageDownloader
    {
        private bool breakDownload;
        private string urlToDownload;
        public NetPercentageDownloader(String url)
        {
            this.urlToDownload = url;
            breakDownload = false;
        }
        public NetPercentageDownloader(String url, DelegateOnPercentageIncreasment eventHandler)
        {
            this.urlToDownload = url;
            this.OnPercentageIncreasment += eventHandler;
            breakDownload = false;
        }

        public void StartDownload()
        {
            downloadData(urlToDownload);
        }
        public void BreakDownload()
        {
            breakDownload = true;
        }

        byte[] DownloadedData { get; set; }
        private bool downloadData(string url)
        {
            DownloadedData = new byte[0];
            try
            {
                //Optional
                Application.DoEvents();

                //Get a data stream from the url
                WebRequest req = WebRequest.Create(url);
                WebResponse response = req.GetResponse();
                Stream stream = response.GetResponseStream();

                //Download in chuncks
                byte[] buffer = new byte[1024];

                int dataLength = (int)response.ContentLength;

                OnPercentageIncreasment(new DownloaderIncreasmentEvent
                {
                    CurrentDataLength = 0,
                    _done = false,
                    Precentage = 0,
                    TotalDataLength = dataLength


                });

                Application.DoEvents();

                MemoryStream memStream = new MemoryStream();
                while (true)
                {
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);

                    if (bytesRead == 0)
                    {
                        //Finished downloading

                        //OnPercentageIncreasment(new DownloaderIncreasmentEvent
                        //{
                        //    CurrentDataLength = dataLength,
                        //    _done = true,
                        //    Precentage = 100,

                        //}
                        //);
                        Application.DoEvents();
                        break;
                    }
                    else
                    {
                        if (!breakDownload)
                        {
                            memStream.Write(buffer, 0, bytesRead);
                            long memlen = memStream.Length;
                            OnPercentageIncreasment(new DownloaderIncreasmentEvent
                            {
                                CurrentDataLength = memlen,
                                _done = false,
                                Precentage = (int)memlen / dataLength,
                                TotalDataLength = dataLength
                            }
                            );
                            Application.DoEvents();
                        }
                        else
                        {
                            //interupt download / break it
                            stream.Flush();
                            stream.Close();
                            return false;
                        }
                    }
                }

                //Convert the downloaded stream to a byte array
                DownloadedData = memStream.ToArray();
                OnPercentageIncreasment(new DownloaderIncreasmentEvent
                {
                    CurrentDataLength = dataLength,
                    _done = true,
                    Precentage = 100,
                }
                );
                //Clean up
                stream.Close();
                memStream.Close();

                OnDownloadComplete(new DownloadComplete { DownloadedData = this.DownloadedData });
                // :) success!
                return true;
            }
            catch (Exception)
            {
                //May not be connected to the internet
                //Or the URL might not exist
                MessageBox.Show("There was an error accessing the URL.");
                return false;
            }
        }
        public delegate void DelegateDownloadComplete(DownloadComplete e);
        public delegate void DelegateOnPercentageIncreasment(DownloaderIncreasmentEvent e);
        public event DelegateOnPercentageIncreasment OnPercentageIncreasment;
        public event DelegateDownloadComplete OnDownloadComplete;
    }
    public class DownloadComplete : EventArgs
    {
        public DownloadComplete()
        {
            this._downloadedData = new byte[0];
        }
        public byte[] DownloadedData
        {
            get { return this._downloadedData; }
            internal set { this._downloadedData = value; }
        }
        private byte[] _downloadedData;
    }
    public class DownloaderIncreasmentEvent : EventArgs
    {
        public DownloaderIncreasmentEvent()
        {
            this._done = false;
        }
        public int Precentage { get; internal set; }
        public long CurrentDataLength { get; internal set; }
        public int TotalDataLength { get; internal set; }
        public bool Done
        {
            get { return this._done; }
            internal set { this._done = value; }
        }
        internal bool _done;
    }
}